package cn.ug.pay.service.impl;

import cn.ug.aop.RemoveCache;
import cn.ug.aop.SaveCache;
import cn.ug.bean.base.DataTable;
import cn.ug.bean.status.DeleteStatus;
import cn.ug.core.ensure.Ensure;
import cn.ug.pay.bean.BillBean;
import cn.ug.pay.bean.request.FinanceBillParam;
import cn.ug.pay.bean.response.ActiveMemberBean;
import cn.ug.pay.bean.status.CommonConstants;
import cn.ug.pay.bean.type.BillType;
import cn.ug.pay.bean.type.TradeType;
import cn.ug.pay.mapper.BillMapper;
import cn.ug.pay.mapper.ProductOrderMapper;
import cn.ug.pay.mapper.entity.Bill;
import cn.ug.pay.service.BillService;
import cn.ug.pay.utils.Common;
import cn.ug.product.bean.response.ProductTradeTimeBean;
import cn.ug.service.impl.BaseServiceImpl;
import cn.ug.util.SerialNumberWorker;
import cn.ug.util.UF;
import com.esotericsoftware.minlog.Log;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static cn.ug.config.CacheType.OBJECT;
import static cn.ug.config.CacheType.SEARCH;

@Service
public class BillServiceImpl extends BaseServiceImpl implements BillService {
	@Resource
	private BillMapper billMapper;
	@Resource
	private DozerBeanMapper dozerBeanMapper;
	@Autowired
	private ProductOrderMapper productOrderMapper;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int save(BillBean entityBean) {
		// 数据完整性校验
		/*if(null == entityBean || StringUtils.isBlank(entityBean.getMemberId())) {
			Ensure.that(true).isTrue("00000002");
		}
		Bill entity = dozerBeanMapper.map(entityBean, Bill.class);
		Bill bill = billMapper.findByOrderId(entity.getOrderId());
		if (bill == null) {
			if(StringUtils.isBlank(entity.getId())) {
				entity.setId(UF.getRandomUUID());
			}
			if(StringUtils.isBlank(entity.getOrderId())) {
				entity.setOrderId(SerialNumberWorker.getInstance().nextId());
			}
			int rows = billMapper.insert(entity);
			Ensure.that(rows).isLt(1,"00000005");
		} else {
			int rows = billMapper.updateTradeTypeByOrderId(bill.getOrderId(), TradeType.ACCOUNT_WITHDRAWAL.getValue(), BillType.OUTLAY.getValue());
			Ensure.that(rows).isLt(1,"00000005");
		}
		return 0;*/
		if(null == entityBean || StringUtils.isBlank(entityBean.getMemberId())) {
			Ensure.that(true).isTrue("00000002");
		}
		Bill entity = dozerBeanMapper.map(entityBean, Bill.class);
		if(StringUtils.isBlank(entity.getId())) {
			entity.setId(UF.getRandomUUID());
		}
		if(StringUtils.isBlank(entity.getOrderId())) {
			entity.setOrderId(SerialNumberWorker.getInstance().nextId());
		}
		int rows = billMapper.insert(entity);
		Ensure.that(rows).isLt(1,"00000005");
		return 0;
	}

	@Override
	public int getTransactionNumForThisMonth(String memberId, int tradeType) {
		if (StringUtils.isNotBlank(memberId)) {
			return billMapper.getTransactionNumForThisMonth(memberId, tradeType);
		}
		return 0;
	}

	@Override
	public int getTransactionNumForThisDay(String memberId, int tradeType) {
		if (StringUtils.isNotBlank(memberId)) {
			return billMapper.getTransactionNumForThisDay(memberId, tradeType);
		}
		return 0;
	}

	@Override
	public int delete(String id) {
		if(StringUtils.isBlank(id)) {
			return 0;
		}

		return billMapper.delete(id);
	}

	@Override
	public int deleteByIds(String[] id){
		if(id == null || id.length<=0){
			return 0;
		}

		return billMapper.deleteByIds(id);
	}

	@Override
	public int removeByIds(String[] id) {
		if(id == null || id.length<=0){
			return 0;
		}

		return billMapper.updateByPrimaryKeySelective(
				getParams()
						.put("id", id)
						.put("deleted", DeleteStatus.YES)
						.toMap()
		);
	}

	@Override
	public BillBean findById(String id) {
		if(StringUtils.isBlank(id)) {
			return null;
		}

		Bill entity = billMapper.findById(id);
		if(null == entity) {
			return null;
		}

		BillBean entityBean = dozerBeanMapper.map(entity, BillBean.class);
		entityBean.setAddTimeString(UF.getFormatDateTime(entity.getAddTime()));
		entityBean.setModifyTimeString(UF.getFormatDateTime(entity.getModifyTime()));
		return entityBean;
	}

	@Override
	public DataTable<BillBean> query(String order, String sort, int pageNum, int pageSize, Integer type, Integer tradeType,
									 BigDecimal amountMin, BigDecimal amountMax, LocalDateTime addTimeMin, LocalDateTime addTimeMax,
									 String memberId, String memberName, String memberMobile, String keyword) {
		Page<BillBean> page = PageHelper.startPage(pageNum, pageSize);
		List<BillBean> list = queryDetail(order, sort, null, type, tradeType, amountMin, amountMax, addTimeMin, addTimeMax,
				memberId, memberName, memberMobile, keyword);
		if (list != null && list.size() > 0) {
			for (BillBean bill : list) {
				int trasactionType = bill.getTradeType() == null ? 0 : bill.getTradeType();
				bill.setRemark(TradeType.getRemark(trasactionType));
			}
		}
		return new DataTable<>(page.getPageNum(), page.getPageSize(), page.getTotal(), list);
	}

	@Override
	public List<BillBean> query(Integer tradeType, LocalDateTime addTimeMin, LocalDateTime addTimeMax) {
		List<BillBean> list = queryDetail(null, null, null, 0, tradeType, null, null, addTimeMin, addTimeMax,
				null, null, null, null);
		if (list != null && list.size() > 0) {
			for (BillBean bill : list) {
				bill.setRemark(TradeType.getRemark(bill.getTradeType()));
			}
		}
		return list;
	}

	@Override
	public List<ActiveMemberBean> findBuySellActiveMemberList(FinanceBillParam financeBillParam) {
		//返回List集合
		List<ActiveMemberBean> resultList = new ArrayList<ActiveMemberBean>();
		financeBillParam.setPageSize(999999999);
		//获取买金用户
		List<String> channelIds = null;
		if(StringUtils.isNotBlank(financeBillParam.getChannelId())) {
			channelIds = Arrays.asList(StringUtils.split(financeBillParam.getChannelId(), ","));
		}
		List<ActiveMemberBean> buyList = productOrderMapper.findBuyActiveMemberList(financeBillParam.getStartTime(),
				financeBillParam.getEndTime(),
				channelIds);
		//获取卖金用户
		financeBillParam.setTradeType(TradeType.SELL_GOLD_INCOME.getValue()+"");
		List<ActiveMemberBean> sellList = billMapper.findBuySellActiveMemberList(financeBillParam.getTradeType(),
				financeBillParam.getStartTime(),
				financeBillParam.getEndTime(),
				channelIds);

		//验证数据是否为空--如果为空不做下一步
		if((buyList == null || buyList.isEmpty()) &&( sellList == null || sellList.isEmpty())){
			return null;
		}

		//获取开始时间
		if(StringUtils.isBlank(financeBillParam.getStartTime())){
			financeBillParam.setStartTime(buyList.get(0).getDay());      //设置为第一条数据
		}
		//获取结束时间
		if(StringUtils.isBlank(financeBillParam.getEndTime())){
			financeBillParam.setEndTime(UF.getFormatDate(LocalDateTime.now()));   //设置为当前时间
		}

		//设置开始时间
		LocalDate startTime = LocalDate.parse(financeBillParam.getStartTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
		LocalDate endTime = LocalDate.parse(financeBillParam.getEndTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
		DateFormat df = new SimpleDateFormat("yyyyMMdd");
		//获取查询出的天数
		int day = Integer.valueOf(Common.until(startTime,endTime) +"") + 1;
		for(int i = 0;i< day;i++){
			//当前日期时间字符串
			String startTimeString = startTime.toString();
			ActiveMemberBean entity = new ActiveMemberBean();
			entity.setDay(startTime.toString());
			String dayNumber = df.format(stringToDate(startTime.toString()));
			entity.setDayNumber(Integer.valueOf(dayNumber));
			if(buyList != null && !buyList.isEmpty()){
				List<ActiveMemberBean> list = buyList.stream().filter(o -> o.getDay().contains(startTimeString)).collect(Collectors.toList());
				if(list != null && !list.isEmpty()){
					entity.setBuyNumber(list.get(0).getNumber());
				}else{
					entity.setBuyNumber(0);
				}
			}else{
				entity.setBuyNumber(0);
			}
			if(sellList != null && !sellList.isEmpty()){
				List<ActiveMemberBean> list = sellList.stream().filter(o -> o.getDay().contains(startTimeString)).collect(Collectors.toList());
				if(list != null && !list.isEmpty()){
					entity.setSellerNumber(list.get(0).getNumber());
				}else{
					entity.setSellerNumber(0);
				}
			}else{
				entity.setSellerNumber(0);
			}
			resultList.add(entity);
			startTime = startTime.plusDays(1);
		}
		return resultList;
	}

	@Override
	public BigDecimal sumAmount(int tradeType, String startDate, String endDate, String memberId) {
		if (tradeType > 0) {
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("tradeType", tradeType);
			if (StringUtils.isNotBlank(startDate)) {
				params.put("startDate", startDate);
			}
			if (StringUtils.isNotBlank(endDate)) {
				params.put("endDate", endDate);
			}
			if (StringUtils.isNotBlank(memberId)) {
				params.put("memberId", memberId);
			}
			return billMapper.sumAmount(params);
		}
		return BigDecimal.ZERO;
	}

	@Override
	public int sumMembers(int tradeType, String startDate, String endDate, String memberId) {
		if (tradeType > 0) {
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("tradeType", tradeType);
			if (StringUtils.isNotBlank(startDate)) {
				params.put("startDate", startDate);
			}
			if (StringUtils.isNotBlank(endDate)) {
				params.put("endDate", endDate);
			}
			if (StringUtils.isNotBlank(memberId)) {
				params.put("memberId", memberId);
			}
			return billMapper.sumMembers(params);
		}
		return 0;
	}

	/**
	 * 获取数据列表
	 * @param order			排序字段
	 * @param sort			排序方式 desc或asc
	 * @param orderId		订单号
	 * @param type			类型 1:收入 2:支出
	 * @param tradeType		交易类型 1:线上充值  2:卖金收入 3:邀请返现 4:账户提现 5:买金支出
	 * @param amountMin		最小收支记录金额
	 * @param amountMax		最大收支记录金额
	 * @param addTimeMin	最小操作时间
	 * @param addTimeMax	最大操作时间
	 * @param memberId		会员ID
	 * @param memberName	会员名称
	 * @param memberMobile	会员手机
	 * @param keyword		关键字
	 * @return				列表
	 */
	private List<BillBean> queryDetail(String order, String sort, String orderId, Integer type, Integer tradeType,
									   BigDecimal amountMin, BigDecimal amountMax, LocalDateTime addTimeMin, LocalDateTime addTimeMax,
									   String memberId, String memberName, String memberMobile, String keyword){
		if(null != addTimeMax) {
			// 加一天减一秒
			addTimeMax = addTimeMax.plusDays(1).minusSeconds(1);
		}
		List<BillBean> dataList = new ArrayList<>();
		List<Bill> list = billMapper.query(
				getParams(keyword, order, sort)
						.put("orderId", orderId)
						.put("type", type)
						.put("tradeType", tradeType)
						.put("amountMin", amountMin)
						.put("amountMax", amountMax)
						.put("addTimeMin", addTimeMin)
						.put("addTimeMax", addTimeMax)
						.put("memberId", memberId)
						.put("memberName", UF.escapeSql(memberName))
						.put("memberMobile", UF.escapeSql(memberMobile))
						.toMap());
		for (Bill o : list) {
			BillBean objBean = dozerBeanMapper.map(o, BillBean.class);
			objBean.setAddTimeString(UF.getFormatDateTime(o.getAddTime()));
			objBean.setModifyTimeString(UF.getFormatDateTime(o.getModifyTime()));
			dataList.add(objBean);
		}
		return dataList;
	}

	@Override
	public BigDecimal getTransactionAmountForThisMonth(String memberId) {
		return billMapper.getTransactionAmountForThisMonth(memberId);
	}

	public static Date stringToDate(String str){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try{
			return sdf.parse(str);
		}catch (Exception e){
			e.printStackTrace();
		}
		return null;
	}
	public static void main(String[] args) {
		DateFormat df= new SimpleDateFormat("yyyyMMdd");//对日期进行格式化
		System.out.println(df.format(stringToDate("")));
	}
}

